#include <iostream>
#include <thread>
#include <vector>

using namespace std;

//transform thread ownship
/* void some_function(); */
/* void some_other_function(); */

/* void test1(){ */
/*     thread t1(some_function);//t1 bind some_function */
/*     thread t2 = move(t1);//t2 get some_function ownship from t1 */

/*     //now t1 don't have bind function */
/*     t1 = thread(some_other_function);//t1 bind some_other_function */

/*     thread t3; */

/*     t3 = move(t2);//t3 get some_function ownship from t2 */

/*     //now t1 has bind function some_other_function */
/*     t1 = move(t3);//error */
/*                   //t1 cannot bind other function */
/*                   //system call std::terminate to shut thread */
/* } */

//std::thread support move
//can move ownship out of function

thread f()
{
    void some_function();

    return thread(some_function);
}

thread g()
{
    void some_other_function();
    thread t(some_other_function);

    return t;
}

//std::thread support move
//can move ownship inside of function
void f1(thread t);

void g1()
{
    void some_function();
    f1(thread(some_function));
    thread t(some_function);

    //seems like a variable send to parameter list
    f1(move(t));
}

//std::thread support move
//can move ownship as parameter of class contribution function parameter
class scoped_thread
{
    thread t;
public:
    //new thread deliver into scoped_thread immediately 
    //rather than create a dependency variable
    explicit scoped_thread(thread t_):t(move(t_)){
        if(!t.joinable())
            throw logic_error("No thread");
    }

    ~scoped_thread(){t.join();}

    scoped_thread(scoped_thread const &) = delete;
    scoped_thread & operator=(scoped_thread const &) = delete;
};

//batch thread
void do_work(unsigned id);

void f2(){
    vector<thread> threads;
    for(unsigned i = 0; i < 20; ++i)
    {
        threads.emplace_back(do_work, i);
    }

    for(auto & entry : threads)
    {
        entry.join();
    }
}


int main()
{
    return 0;
}

